package relop;

/**
 * The selection operator specifies which tuples to retain under a condition; in
 * Minibase, this condition is simply a set of independent predicates logically
 * connected by OR operators.
 */
public class Selection extends Iterator {

	private Iterator iter;
	private Predicate[] preds;
	private Tuple nextTuple;
	
	/**
	 * Constructs a selection, given the underlying iterator and predicates.
	 */
	public Selection(Iterator iter, Predicate... preds) {
		this.schema = iter.schema;
		this.iter = iter;
		this.preds = preds;
		nextTuple = null;
	}

	/**
	 * Gives a one-line explaination of the iterator, repeats the call on any
	 * child iterators, and increases the indent depth along the way.
	 */
	public void explain(int depth) {
		indent(depth);
		String explaination = "Selection with predicates: ";
		for(int i = 0; i < preds.length; i++) {
			if(i == 0)
				explaination += preds[i].toString();
			else
				explaination += " OR " + preds[i].toString();
		}
		System.out.println(explaination);
		iter.explain(depth + 1);
	}

	/**
	 * Restarts the iterator, i.e. as if it were just constructed.
	 */
	public void restart() {
		iter.restart();
		nextTuple = null;
	}

	/**
	 * Returns true if the iterator is open; false otherwise.
	 */
	public boolean isOpen() {
		return iter.isOpen();
	}

	/**
	 * Closes the iterator, releasing any resources (i.e. pinned pages).
	 */
	public void close() {
		iter.close();
		nextTuple = null;
	}

	/**
	 * Returns true if there are more tuples, false otherwise.
	 */
	public boolean hasNext() {
		if(!isOpen())
			return false;
		
		while(iter.hasNext()) {
			boolean pass = false;
			Tuple tmpTuple = iter.getNext();
			for(Predicate pred : preds) {
				if(pred.evaluate(tmpTuple)) {
					pass = true;
					break;
				}
			}
			
			if(pass) {
				nextTuple = tmpTuple;
				return true;
			}
		}
		
		nextTuple = null;
		return false;
	}

	/**
	 * Gets the next tuple in the iteration.
	 * 
	 * @throws IllegalStateException
	 *             if no more tuples
	 */
	public Tuple getNext() {
		if(nextTuple == null)
			throw new IllegalStateException("getNext(): no more tuples");
		
		return nextTuple;
	}

} // public class Selection extends Iterator
